package com.auroramanito.uaa.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;


@With
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "mooc_roles")
public class Role implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(name = "role_name",unique = true,nullable = false,length = 50)
    private String roleName;

    @NotNull
    @Size(max = 50)
    @Column(name = "display_name", nullable = false, length = 50)
    private String displayName;

    /**
     * FetchType.LAZY: 懒加载，在访问关联对象的时候加载(即从数据库读入内存)
     * FetchType.EAGER:立刻加载，在查询主对象的时候同时加载关联对象。
     *
     * @Fetch(FetchMode.JOIN)： 始终立刻加载，使用外连(outer join)查询的同时加载关联对象，忽略FetchType.LAZY设定。
     * @Fetch(FetchMode.SELECT) ：默认懒加载(除非设定关联属性lazy=false)，当访问每一个关联对象时加载该对象，会累计产生N+1条sql语句
     * @Fetch(FetchMode.SUBSELECT) 默认懒加载(除非设定关联属性lazy = false), 在访问第一个关联对象时加载所有的关联对象。且FetchType设定有效。
     * */
    @JsonIgnore
    @Fetch(FetchMode.JOIN)
    @ManyToMany
    @JoinTable(name = "mooc_roles_permissions",
    joinColumns = {@JoinColumn(name = "role_id",referencedColumnName ="id")},
            inverseJoinColumns = {@JoinColumn(name = "permission_id",referencedColumnName = "id")}
    )
    private Set<Permission> permissions = new HashSet<>();

    /**
     * 1>只有OneToOne，OneToMany，ManyToMany上才有mappedBy属性，ManyToOne不存在该属性；
     * 2>mappedBy标签一定是定义在被拥有方的，他指向拥有方；
     * 3>mappedBy的含义，应该理解为，拥有方能够自动维护跟被拥有方的关系，当然，如果从被拥有方，通过手工强行来维护拥有方的关系也是可以做到的；
     * 4>mappedBy跟joinColumn/JoinTable总是处于互斥的一方，可以理解为正是由于拥有方的关联被拥有方的字段存在，拥有方才拥有了被拥有方。mappedBy这方定义JoinColumn/JoinTable总是失效的，不会建立对应的字段或者表。
     *
     * mappedBy表示声明自己不是一对多的关系维护端，由对方来维护，是在一的一方进行声明的。mappedBy的值应该为一的一方的表名。
     * */
    @JsonIgnore
    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}
